﻿namespace Octopus.VMDeployer

open System
open System.IO
open System.ServiceProcess


type DeployerService =
  inherit System.ServiceProcess.ServiceBase
  
  val serviceBinPath : string
  
  new() as x =
    {
      serviceBinPath = let s = typeof<DeployerInstaller>.Assembly.Location in s.Substring(0, s.LastIndexOf(@"\"))
    }
    then
      x.ServiceName <- "Octopus VM Deployer"


  //--
  
  member private x.waitForNetworkConnection () =
    while not( System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable() ) do
      System.Threading.Thread.Sleep(1000)
    System.Threading.Thread.Sleep(1000)

  member private x.configureMachine (xmlPath:string) =
    use log = File.AppendText(x.serviceBinPath + @"\log.txt", AutoFlush=true)
    log.WriteLine("-------------------------------------------------------")
    log.WriteLine("Session started at: " + System.DateTime.Now.ToString())
    log.WriteLine()

    let data = ConfigurationData.FromXmlFile(xmlPath)
    
    log.WriteLine("Configuring this Virtual Machines, owned by " + data.OwnerName)
    log.WriteLine()
        
    try
        log.WriteLine("Waiting for network connection")
        x.waitForNetworkConnection ()
        
        if data.IsFinished then
          log.WriteLine("Deployment finished, deleting the conf.")
          System.IO.File.Delete(xmlPath)
        else
          log.WriteLine("Executing the deployment...")
          
          let mutable excepted = false
          try
            data.ExecuteDeploy(log)
          with _ ->
            excepted <- true
          
          if excepted then
            log.WriteLine("Deployment failed, deleting the conf")
            System.IO.File.Delete(xmlPath)
          else if data.IsFinished then
            log.WriteLine("Deployment finished, deleting the conf")
            System.IO.File.Delete(xmlPath)
          else
            log.WriteLine("Deployment not finished. Saving the conf then reboot.")
            data.ToXmlFile(xmlPath)       // update
            data.Reboot()

    finally
        log.WriteLine()
        log.Close()
        x.Stop()
  

  //--
  
  member x.StartService (args:string array) =
    async {
      let localConf = x.serviceBinPath + @"\octopusDeployer.xml"

      // checks for the configuration xml file in the service directory
      // (if exists, the deployment has to be resumed)
      if File.Exists(localConf) then
        x.configureMachine localConf

      // checks for the configuration xml file (in the floppy drive)
      else if File.Exists(@"A:\octopusDeployer.xml") then
        File.Move(@"A:\octopusDeployer.xml", localConf)
        x.configureMachine localConf

      // do nothing
      else
        use log = File.AppendText(x.serviceBinPath + @"\log.txt", AutoFlush=true)
        log.WriteLine("-------------------------------------------------------")
        log.WriteLine("Session started at: " + System.DateTime.Now.ToString())
        log.WriteLine()
        log.WriteLine("Configuration file not found. Stopping the service.");
        log.WriteLine()
        log.Close()
        x.Stop()
    }
      
  override x.OnStart (args:string array) =
    Async.Start (x.StartService args)

  override x.OnStop() =
    ()

  member x.OnDebugStart (args:string array) = x.OnStart(args)
  member x.OnDebugStop () = x.OnStop()
    


//
//-------------------------------------------------------------
//

module Main =
  let servicesToRun : ServiceBase array = [| new DeployerService() |]
  ServiceBase.Run(servicesToRun)
  